; void pixelar_asm (
; 	unsigned char *src, RDI
; 	unsigned char *dst, RSI
; 	int m, EDX
; 	int n, ECX
; 	int src_row_size, R8d
; 	int dst_row_size  R9d
; );

section .data

section .text

global pixelar_asm

pixelar_asm:

	push R12		; en R13 voy a guardar el salto de filas del src
	push R13		; en R12 voy a guardar el salto de filas del dst
	push R14		; en R14 voy a contar las columnas
	push R15		; en R15 voy a contar las filas
	push RBX		; en RBX es una suma provisoria de rdi + filas
	xor R14, R14		; R14 = 0
	xor R15, R15		; R15 = 0
	xor RAX, RAX		; RAX = 0
	mov EAX, R8d		; EAX = src_row_size
	xor R8, R8		; R8 = 0
	mov R8, RAX		; R8 = src_row_size
	mov EAX, R9d		; EAX = dst_row_size
	xor R9, R9		; R9 = 0
	mov R9, RAX		; R9 = dst_row_size
	mov R12, R8		; pongo la longitud de fila de src en R12
	add R12, R8		; lo "multiplico" x3
	add R12, R8		;  " ; evito perder RDX de esta manera
	mov R13, R9		; pongo la longitud de fila de dst en R13
	add R13, R9		; lo "multiplico" x3
	add R13, R9		;  " ; evito perder RDX de esta manera
				; en XMM7 voy a ir guardando el promedio

.ciclo_filas:

	.ciclo_columnas:

		; TRABAJO DE A TRAMOS DE 4 FILAS, VOY A TOMAR POR CADA FILA DE A 8 BYTES

		; LEVANTO DEL SRC 8 BYTES DE ESTE TRAMO DE 4 FILAS
		xor RBX, RBX			; RBX = 0
		movq XMM0, [RDI+RBX]		; levanto 8 bytes de esta fila, dos datos
		add RBX, R8			; paso de fila
		movq XMM1, [RDI+RBX]		; levanto 8 bytes de esta fila, dos datos
		add RBX, R8			; paso de fila
		movq XMM2, [RDI+RBX]		; levanto 8 bytes de esta fila, dos datos
		add RBX, R8			; paso de fila
		movq XMM3, [RDI+RBX]		; levanto 8 bytes de esta fila, dos datos
		; FIN LEVANTO DEL SRC 8 BYTES DE ESTE TRAMO DE 4 FILAS

		pxor XMM4, XMM4			; XMM4 = 0
		punpcklbw XMM0, XMM4		; 0|x7|0|x6|0|x5|0|x4|0|x3|0|x2|0|x1|0|x0|
						; dato 1 = 0|x7|0|x6|0|x5|0|x4|, dato2 = x3|0|x2|0|x1|0|x0|
		pxor XMM4, XMM4			; XMM4 = 0
		punpcklbw XMM1, XMM4		; 0|x7|0|x6|0|x5|0|x4|0|x3|0|x2|0|x1|0|x0|
						; dato 1 = 0|x7|0|x6|0|x5|0|x4|, dato2 = x3|0|x2|0|x1|0|x0|
		pxor XMM4, XMM4			; XMM4 = 0
		punpcklbw XMM2, XMM4		; 0|x7|0|x6|0|x5|0|x4|0|x3|0|x2|0|x1|0|x0|
						; dato 1 = 0|x7|0|x6|0|x5|0|x4|, dato2 = x3|0|x2|0|x1|0|x0|
		pxor XMM4, XMM4			; XMM4 = 0
		punpcklbw XMM3, XMM4		; 0|x7|0|x6|0|x5|0|x4|0|x3|0|x2|0|x1|0|x0|
						; dato 1 = 0|x7|0|x6|0|x5|0|x4|, dato2 = x3|0|x2|0|x1|0|x0|

		; al momento tengo en XMM0/1/2/3 H las 4 filas del dato1 y en XMM0/1/2/3 L las 4 filas del dato2

		paddw XMM0, XMM1			; sumo las filas 1 con 2
		paddw XMM0, XMM2			; sumo las filas 1 y 2 con 3
		paddw XMM0, XMM3			; sumo las filas 1 y 2 y 3 con 4

		; al momento en XMM0 H tengo las sumas verticales del dato1 y en XMM0 L tengo las sumas verticales del dato2
		; me resta realizar las dos sumas horizontales de las momentaneas sumas verticales del dato1 y 2

		movdqu XMM1, XMM0		; copio los datos a XMM1 | XMM0 = x7|x6|x5|x4|x3|x2|x1|x0|
		psrld XMM1, 16			; XMM1 = 0|x7|0|x5|0|x3|0|x1|
		paddw XMM0, XMM1		; XMM0 = x7|   x6|x5|   x4|x3|   x2|x1|   x0|
						; XMM1 =  0|   x7| 0|   x5| 0|   x3| 0|   x1|
						; XMM0 = x7|x7+x6|x5|x5+x4|x3|x3+x2|x1|x1+x0|

		movdqu XMM1, XMM0		; XMM1 = x7|x7+x6|x5|x5+x4|x3|x3+x2|x1|x1+x0|
		psrlq XMM1, 32			; XMM1 = 0|0|x7|x7+x6|0|0|x3|x3+x2|
		paddd XMM0, XMM1		; XMM0 = x7|x7+x6|   x5|      x5+x4|x3|x3+x2|   x1|	 x1+x0|
						; XMM1 =  0|    0|   x7|      x7+x6| 0|    0|   x3|	 x3+x2|
						; XMM0 = x7|x7+x6|x5+x7|x5+x4+x7+x6|x3|x3+x2|x1+x3|x1+x0+x3+x2|
						; XMM0 = x7|x7+x6|x5+x7|suma hor d1|x3|x3+x2|x1+x3|suma hor d2|

		psllq XMM0, 48			; XMM0 = |suma hor d1|0|0|0|suma hor d2|0|0|0|
		psrlq XMM0, 48			; XMM0 = |0|0|0|suma hor d1|0|0|0|suma hor d2|

		psrlw XMM0, 4			; XMM0 = |0|0|0|(suma hor d1)/16|0|0|0|(suma hor d2)/16|

		; ahora en xmm0 tengo los promedios XMM0 = |0|0|0|promedio d1|0|0|0|promedio d2|
					
		movdqu XMM1, XMM0		; XMM1 = |0|0|0|promedio d1|0|0|0|promedio d2|
		psrldq XMM1, 4			; XMM1 = |0|0|0|0|0|promedio d1|0|promedio d2|
		paddd XMM0, XMM1		; XMM0 = |0|0|0|promedio d1|0|          0|0|promedio d2|
						; XMM1 = |0|0|0|          0|0|promedio d1|0|	      0|
						; XMM0 = |0|0|0|promedio d1|0|promedio d1|0|promedio d2|

		movdqu XMM1, XMM0		; XMM1 = |0|0|0|promedio d1|0|promedio d1|0|promedio d2|
		pslldq XMM1, 2			; XMM1 = |0|0|promedio d1|0|promedio d1|0|promedio d2|0|
		paddd XMM0, XMM1		; XMM0 = |0|0|          0|promedio d1|          0|promedio d1|          0|promedio d2|
						; XMM1 = |0|0|promedio d1|          0|promedio d1|          0|promedio d2|          0|
						; XMM0 = |0|0|promedio d1|promedio d1|promedio d1|promedio d1|promedio d2|promedio d2|

		movdqu XMM1, XMM0		; XMM1 = |0|0|promedio d1|promedio d1|promedio d1|promedio d1|promedio d2|promedio d2|
		psllw XMM1, 8			; XMM1 = |0|0|0|0|p1|0|p1|0|p1|0|p1|0|p2|0|p2|0|
		paddb XMM0, XMM1		; XMM0 = |0|0|0|0| 0|p1| 0|p1| 0|p1| 0|p1| 0|p2| 0|p2|
						; XMM1 = |0|0|0|0|p1| 0|p1| 0|p1| 0|p1| 0|p2| 0|p2| 0|
						; XMM0 = |0|0|0|0|p1|p1|p1|p1|p1|p1|p1|p1|p2|p2|p2|p2|
						; XMM0 = |             basura|     p1 x 4|     p2 x 4|
		
	
		; SETEO EN EL DST 8 BYTES DE ESTE TRAMO DE 4 FILAS
		xor RBX, RBX			; RBX = 0
		movq [RSI], XMM0		; seteo la fila 1 del tramo
		add RBX, R9			; paso de fila
		movq [RSI+RBX], XMM0		; seteo la fila 2 del tramo
		add RBX, R9			; paso de fila
		movq [RSI+RBX], XMM0		; seteo la fila 3 del tramo
		add RBX, R9			; paso de fila
		movq [RSI+RBX], XMM0		; seteo la fila 4 del tramo
		; FIN SETEO EN EL DST 8 BYTES DE ESTE TRAMO DE 4 FILAS

		add RDI, 8			; situo el src en las proximas 8 columnas
		add RSI, 8			; situo el dst en las proximas 8 columnas
		add R14d, 8			; incremento el contador de columnas en 8
		cmp R14d, ECX			; me fijo si el contador ya llego al final de la fila
		jl .ciclo_columnas 		; si no llego sigo procesando columnas
	.fin_ciclo_columnas:
	
	add RDI, R12				; en R12 tenia el incremento de filas del src, lo sumo al src
	add RSI, R13				; en R13 tenia el incremento de filas del dst, lo sumo al dst
	xor R14, R14				; reseteo el contador de columnas
	add R15d, 4				; incremento el contador de filas
	cmp R15d, EDX				; me dijo si recorri todas las filas
	jl .ciclo_filas				; si todavia me faltan sigo procesando
.fin_ciclo_filas:

	


.fin:
	pop RBX
	pop R15
	pop R14
	pop R13
	pop R12
	ret

